home *** CD-ROM | disk | FTP | other *** search
- /*
- * STevie - ST editor for VI enthusiasts. ...Tim Thompson...twitch!tjt...
- */
-
- #include <ctype.h>
- #include "stevie.h"
-
- /*
- * normal
- *
- * Execute a command in normal mode.
- */
-
- normal(c)
- int c;
- {
- char *p, *q;
- int nchar, n;
-
- switch(c){
- case 'H':
- help();
- /* fall through purposely */
- case '\014':
- screenclear();
- updatescreen();
- break;
- case 04:
- /* control-d */
- if ( ! onedown(10) )
- beep();
- break;
- case 025:
- /* control-u */
- if ( ! oneup(10) )
- beep();
- break;
- case 06:
- /* control-f */
- if ( ! onedown(Rows) )
- beep();
- break;
- case 02:
- /* control-b */
- if ( ! oneup(Rows) )
- beep();
- break;
- case '\007':
- fileinfo();
- break;
- case 'G':
- gotoline(Prenum);
- break;
- case 'l':
- if ( ! oneright() )
- beep();
- break;
- case 'h':
- if ( ! oneleft() )
- beep();
- break;
- case 'k':
- if ( ! oneup(1) )
- beep();
- break;
- case 'j':
- if ( ! onedown(1) )
- beep();
- break;
- case 'b':
- /* If we're on the first character of a word, force */
- /* an initial backup. */
- if ( ! issepchar(*Curschar) && Curschar>Filemem
- && issepchar(*(Curschar-1)) )
- Curschar--;
-
- if ( ! issepchar(*Curschar) ) {
- /* If we start in the middle of a word, back */
- /* up until we hit a separator. */
- while ( Curschar>Filemem && !issepchar(*Curschar))
- Curschar--;
- if ( issepchar(*Curschar) )
- Curschar++;
- }
- else {
- /* back up past all separators. */
- while ( Curschar>Filemem && issepchar(*Curschar))
- Curschar--;
- /* back up past all non-separators. */
- while (Curschar>Filemem && !issepchar(*Curschar)){
- Curschar--;
- }
- if ( issepchar(*Curschar) )
- Curschar++;
- }
- break;
- case 'w':
- if ( issepchar(*Curschar) ) {
- /* If we're on a separator, we advance to */
- /* the next non-separator char. */
- while ( (p=Curschar+1) < Fileend ) {
- Curschar = p;
- if ( ! issepchar(*Curschar) )
- break;
- }
- }
- else {
- /* If we're in the middle of a word, we */
- /* advance to the next word-separator. */
- while ( (p=Curschar+1) < Fileend ) {
- Curschar = p;
- if ( issepchar(*Curschar) )
- break;
- }
- /* Now go past any trailing white space */
- while (isspace(*Curschar) && (Curschar+1)<Fileend)
- Curschar++;
- }
- break;
- case '$':
- while ( oneright() )
- ;
- break;
- case '0':
- case '^':
- beginline();
- break;
- case 'x':
- /* Can't do it if we're on a blank line. (Actually it */
- /* does work, but we want to match the real 'vi'...) */
- if ( *Curschar == '\n' )
- beep();
- else {
- addtobuff(Redobuff,'x',NULL);
- /* To undo it, we insert the same character back. */
- resetundo();
- addtobuff(Undobuff,'i',*Curschar,'\033',NULL);
- Uncurschar = Curschar;
- delchar();
- updatescreen();
- }
- break;
- case 'a':
- /* Works just like an 'i'nsert on the next character. */
- if ( Curschar < (Fileend-1) )
- Curschar++;
- resetundo();
- startinsert("a");
- break;
- case 'i':
- resetundo();
- startinsert("i");
- break;
- case 'o':
- opencmd();
- updatescreen();
- resetundo();
- startinsert("o");
- break;
- case 'd':
- nchar = vgetc();
- n = (Prenum==0?1:Prenum);
- switch(nchar){
- case 'd':
- sprintf(Redobuff,"%ddd",n);
- /* addtobuff(Redobuff,'d','d',NULL); */
- beginline();
- resetundo();
- Uncurschar = Curschar;
- yankline(n);
- delline(n);
- beginline();
- updatescreen();
- /* If we have backed xyzzy, then we deleted the */
- /* last line(s) in the file. */
- if ( Curschar < Uncurschar ) {
- Uncurschar = Curschar;
- nchar = 'p';
- }
- else
- nchar = 'P';
- addtobuff(Undobuff,nchar,NULL);
- break;
- case 'w':
- addtobuff(Redobuff,'d','w',NULL);
- resetundo();
- delword(1);
- Uncurschar = Curschar;
- updatescreen();
- break;
- }
- break;
- case 'c':
- nchar = vgetc();
- switch(nchar){
- case 'c':
- resetundo();
- /* Go to the beginning of the line */
- beginline();
- yankline(1);
- /* delete everything but the newline */
- while ( *Curschar != '\n' )
- delchar();
- startinsert("cc");
- updatescreen();
- break;
- case 'w':
- resetundo();
- delword(0);
- startinsert("cw");
- updatescreen();
- break;
- }
- break;
- case 'y':
- nchar = vgetc();
- switch(nchar){
- case 'y':
- yankline(Prenum==0?1:Prenum);
- break;
- default:
- beep();
- }
- break;
- case '>':
- nchar = vgetc();
- n = (Prenum==0?1:Prenum);
- switch(nchar){
- case '>':
- tabinout(0,n);
- updatescreen();
- break;
- default:
- beep();
- }
- break;
- case '<':
- nchar = vgetc();
- n = (Prenum==0?1:Prenum);
- switch(nchar){
- case '<':
- tabinout(1,n);
- updatescreen();
- break;
- default:
- beep();
- }
- break;
- case '?':
- case '/':
- case ':':
- readcmdline(c);
- break;
- case 'n':
- repsearch();
- break;
- case 'C':
- case 'D':
- p = Curschar;
- while ( Curschar >= p )
- delchar();
- updatescreen();
- resetundo(); /* This should really go above the */
- /* delchars above, and the undobuff should */
- /* be constructed by them. */
- if ( c == 'C' ) {
- Curschar++;
- startinsert("C");
- }
- break;
- case 'r':
- nchar = vgetc();
- resetundo();
- if ( nchar=='\n' || (!Binary && nchar=='\r') ) {
- /* Replacing a char with a newline breaks the */
- /* line in two, and is special. */
- nchar = '\n'; /* convert \r to \n */
- /* Save stuff necessary to undo it, by joining */
- Uncurschar = Curschar-1;
- addtobuff(Undobuff,'J','i',*Curschar,'\033',NULL);
- /* Change current character. */
- *Curschar = nchar;
- /* We don't want to end up on the '\n' */
- if ( Curschar > Filemem )
- Curschar--;
- else if (Curschar < Fileend )
- Curschar++;
- }
- else {
- /* Replacing with a normal character */
- addtobuff(Undobuff,'r',*Curschar,NULL);
- Uncurschar = Curschar;
- /* Change current character. */
- *Curschar = nchar;
- }
- /* Save stuff necessary to redo it */
- addtobuff(Redobuff,'r',nchar,NULL);
- updatescreen();
- break;
- case 'p':
- putline(0);
- break;
- case 'P':
- putline(1);
- break;
- case 'J':
- for ( p=Curschar; *p!= '\n' && p<(Fileend-1) ; p++ )
- ;
- if ( p >= (Fileend-1) ) {
- beep();
- break;
- }
- Curschar = p;
- delchar();
- resetundo();
- Uncurschar = Curschar;
- addtobuff(Undobuff,'i','\n','\033',NULL);
- addtobuff(Redobuff,'J',NULL);
- updatescreen();
- break;
- case '.':
- stuffin(Redobuff);
- break;
- case 'u':
- if ( Uncurschar != NULL && *Undobuff != '\0' ) {
- Curschar = Uncurschar;
- stuffin(Undobuff);
- *Undobuff = '\0';
- }
- if ( Undelchars > 0 ) {
- Curschar = Uncurschar;
- /* construct the next Undobuff and Redobuff, which */
- /* will re-insert the characters we're deleting. */
- p = Undobuff;
- q = Redobuff;
- *p++ = *q++ = 'i';
- while ( Undelchars-- > 0 ) {
- *p++ = *q++ = *Curschar;
- delchar();
- }
- /* Finish constructing Uncursbuff, and Uncurschar */
- /* is left unchanged. */
- *p++ = *q++ = '\033';
- *p = *q = '\0';
- /* Undelchars has been reset to 0 */
- updatescreen();
- }
- break;
- default:
- beep();
- break;
- }
- }
-
- /*
- * tabinout(inout,num)
- *
- * If inout==0, add a tab to the begining of the next num lines.
- * If inout==1, delete a tab from the begining of the next num lines.
- */
-
- tabinout(inout,num)
- {
- int ntodo = num;
- char *savecurs, *p;
-
- beginline();
- savecurs = Curschar;
- while ( ntodo-- > 0 ) {
- beginline();
- if ( inout == 0 )
- inschar('\t');
- else {
- if ( *Curschar == '\t' )
- delchar();
- }
- if ( ntodo > 0 ) {
- if ( (p=nextline(Curschar)) != NULL )
- Curschar = p;
- else
- break;
- }
- }
- /* We want to end up where we started */
- Curschar = savecurs;
- updatescreen();
- /* Construct re-do and un-do stuff */
- sprintf(Redobuff,"%d%s",num,inout==0?">>":"<<");
- resetundo();
- Uncurschar = savecurs;
- sprintf(Undobuff,"%d%s",num,inout==0?"<<":">>");
- }
-
- startinsert(initstr)
- char *initstr;
- {
- char *p, c;
-
- Insstart = Curschar;
- Ninsert = 0;
- Insptr = Insbuff;
- for (p=initstr; (c=(*p++))!='\0'; )
- *Insptr++ = c;
- State = INSERT;
- windrefresh();
- }
-
- resetundo()
- {
- Undelchars = 0;
- *Undobuff = '\0';
- Uncurschar = NULL;
- }
-